package org.budo.support.servlet.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;

import org.budo.support.java.collection.wrapper.NiceToStringMapWrapper;
import org.budo.support.lang.util.NumberUtil;
import org.budo.support.lang.util.StringUtil;

/**
 * @author limingwei2
 */
public class QueryStringUtil {
    public static String mapToQueryString(Map<String, String[]> parameters, Function valueFunction) {
        String queryString = "";
        if (null == parameters || parameters.isEmpty()) {
            return queryString;
        }

        boolean first = true;
        for (Object param : parameters.entrySet()) {
            Entry entry = (Entry) param;
            Object key = entry.getKey();
            Object value = entry.getValue();
            if (null == value) {
                continue;
            }

            Object[] valueArray = value.getClass().isArray() //
                    ? (Object[]) value //
                    : new Object[] { value }; // 不是数组 转为数组

            for (Object valueEach : valueArray) {
                if (!first) {
                    queryString += "&";
                } else {
                    first = false;
                }

                Object _value = null == valueFunction ? valueEach : valueFunction.apply(valueEach);
                queryString += key + "=" + _value;
            }
        }

        return queryString;
    }

    /**
     * 会跳过值为空的项
     */
    public static String mapToQueryString(Map parameters) {
        return mapToQueryString(parameters, null);
    }

    public static Map<String, String[]> queryStringToMap(String queryString) {
        if (StringUtil.isEmpty(queryString)) {
            return new HashMap<String, String[]>();
        }

        int a = queryString.indexOf('?');
        if (a > -1) {
            queryString = queryString.substring(a + 1);
        }

        Map<String, List<String>> map = new HashMap<String, List<String>>();
        String[] pairs = queryString.split("&");

        for (String pair : pairs) {
            String[] keyValue = pair.split("=");
            String key = keyValue[0];
            String value = keyValue.length == 1 ? null : keyValue[1];
            List<String> values = map.get(key);

            if (null == values) {
                values = new ArrayList<String>();
                values.add(value);
                map.put(key, values);
            } else {
                values.add(value);
            }
        }

        Map<String, String[]> result = new HashMap<String, String[]>();
        for (Entry<String, List<String>> entry : map.entrySet()) {
            List<String> value = entry.getValue();
            String[] array = value.toArray(new String[value.size()]);
            result.put(entry.getKey(), array);
        }

        return new NiceToStringMapWrapper(result);
    }

    public static Integer getParameterInteger(String queryString, String key) {
        return getParameterInteger(queryString, key, null);
    }

    public static Integer getParameterInteger(String queryString, String key, Integer defaultValue) {
        Map<String, String[]> map = queryStringToMap(queryString);
        String[] values = map.get(key);

        if (null == values || values.length < 1 || StringUtil.isEmpty(values[0])) {
            return defaultValue;
        }

        return NumberUtil.toInteger(values[0]);
    }

    public static String getParameter(String queryString, String key, String defaultValue) {
        Map<String, String[]> map = queryStringToMap(queryString);
        String[] values = map.get(key);

        if (null == values || values.length < 1 || StringUtil.isEmpty(values[0])) {
            return defaultValue;
        }

        return values[0];
    }

    public static String getParameter(String queryString, String key) {
        return getParameter(queryString, key, null);
    }

    // DruidStatService.getParameters
    public static Map<String, String> queryStringToStringMap(String url) {
        if (url == null || (url = url.trim()).length() == 0) {
            return Collections.<String, String>emptyMap();
        }

        String parametersStr = StringUtil.subString(url, "?", null);
        if (parametersStr == null || parametersStr.length() == 0) {
            return Collections.<String, String>emptyMap();
        }

        String[] parametersArray = parametersStr.split("&");
        Map<String, String> parameters = new LinkedHashMap<String, String>();

        for (String parameterStr : parametersArray) {
            int index = parameterStr.indexOf("=");
            if (index <= 0) {
                continue;
            }

            String name = parameterStr.substring(0, index);
            String value = parameterStr.substring(index + 1);
            parameters.put(name, value);
        }
        return parameters;
    }

    public static String removeQueryString(String url) {
        if (null == url) {
            return url;
        }

        int idx = url.indexOf('?');
        if (idx < 0) {
            return url;
        }

        return url.substring(0, idx);
    }

    /**
     * 参数中是否有空值
     */
    public static Boolean hasNullValue(Map<String, String[]> map) {
        if (null == map || map.isEmpty()) {
            return false;
        }

        for (Entry<String, String[]> entry : map.entrySet()) {
            if (null == entry.getValue() || entry.getValue().length < 1) {
                return true;
            }

            for (String val : entry.getValue()) {
                if (null == val || val.trim().isEmpty()) {
                    return true;
                }
            }
        }

        return false;
    }
}